package apps.business.process.sales.booking;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import promis.utility.CommonService;

import jpa.entitys.promis.common.CostProject;
import jpa.entitys.synchro.staging.SdCustomerOutb1;
import sap.business.sd.outbound.VwSyncMktCustomerService;

import apps.promis.in.common.ProjectAction;
import apps.promis.out.sales.VwSyncMktBookConstructionAction;
import apps.promis.out.sales.VwSyncMktCustomerAction;

public class SalesBookingThreadPoolTest {	
	private static final Logger log = Logger.getLogger(SalesBookingThreadPoolTest.class);
	
	public static void main(String[] args) throws Exception {
		/*
	    if (args.length != 2) {
	      System.out.println("Tests the ThreadPool task.");
	      System.out.println("Usage: java ThreadPoolTest numTasks numThreads");
	      System.out.println("  numTasks - integer: number of task to run.");
	      System.out.println("  numThreads - integer: number of threads " + "in the thread pool.");
	      return;
	    }*/

		List<CostProject> lst1 = new ProjectAction().findAll();
		log.info("CostProject Size:"+ CommonService.getSize(lst1));
		
		System.out.println("CostProject Size:"+ CommonService.getSize(lst1));
		System.out.print("Please any key : "); System.in.read();
		
		List<String> docType_list = new ArrayList<String>();
		docType_list.add("BS");
		docType_list.add("CS");
		docType_list.add("CH");
		
		
		for(String docType : docType_list)
		{
			for(CostProject project : lst1){
				int totalRow = -1;
		    	List<Object[]> lst = null;
		    	try{	    		
		    		lst = new VwSyncMktBookConstructionAction().findAllByProject(project.getId().getCompany(), project.getId().getProject(), docType);				
		    		if(lst != null){
		    			totalRow = lst.size();    	
		    			log.info("totalRow = " + totalRow);
		    		}  		    		
		    	}catch(Exception e)
		    	{
		    		log.error(e.getMessage());
					System.err.println(e.getMessage());
		    	}
		    	
		    	/////////////////////////////////////////////////////////////////////////
			    int numTasks = totalRow;	    
			    int numThreads = 30;
			    
			    log.info("numTasks = " + numTasks);
			    log.info("numThreads = " + numThreads);

			    // create the thread pool
			    ThreadPool threadPool = new ThreadPool(numThreads);

			    // run example tasks
			    for (int i = 0; i < numTasks; i++) {
			    	
			    	Object[] value = lst.get(i);
					String BookingOrContarctNo = CommonService.IsNullRNull(value[2]);
					String status = CommonService.IsNullRNull(value[3]);
					String syncIsstaging = CommonService.IsNullRNull(value[4]);
					String issync = "N";
					
					threadPool.runTask(createTask(project.getId().getCompany(), project.getId().getProject(), BookingOrContarctNo, status, syncIsstaging, issync, i) );   
				}
			    
			    // close the pool and wait for all tasks to finish.
				   threadPool.join();
			  }
		}
	}

	  /**
	   * Creates a simple Runnable that prints an ID, waits 500 milliseconds, then
	   * prints the ID again.
	   */
	  private static Runnable createTask(final String company, final String project, final String BookingOrContarctNo, final String status, final String syncIsstaging, final String issync, final int taskID) {
	    return new Runnable() {
	      public void run() {
	        System.out.println("Task " + taskID + " , customer "+ company+ " , project "+ project+ " , BookingOrContarctNo "+ BookingOrContarctNo+ " , status "+ status+ "  , syncIsstaging "+ syncIsstaging+ " , issync "+ issync+ " : start" + (new Date()));

	        // simulate a long-running task
	        ////////////////////////////////////////////////////////////////////////////////////////
	        
	        try {
				
	        	//new SalesBookingSingleProcessing().ProcessingForRMS(company, project, BookingOrContarctNo, status, syncIsstaging, issync);
				
			} catch (Exception e) {
				log.error(e.getMessage());
				System.err.println(e.getMessage());
			}
	        
	        
	        //////////////////////////////////////////////////////////////////////////////////////
	        try {
	          Thread.sleep(600);
	        } catch (InterruptedException ex) {
	        	log.error(ex.getMessage());
				System.err.println(ex.getMessage());
	        }
	      }
	    };
	  }

	}
	/**
	 * A thread pool is a group of a limited number of threads that are used to
	 * execute tasks.
	 */

	class ThreadPool extends ThreadGroup {

	  private boolean isAlive;

	  private LinkedList taskQueue;

	  private int threadID;

	  private static int threadPoolID;

	  /**
	   * Creates a new ThreadPool.
	   * 
	   * @param numThreads
	   *            The number of threads in the pool.
	   */
	  public ThreadPool(int numThreads) {
	    super("ThreadPool-" + (threadPoolID++));
	    setDaemon(true);

	    isAlive = true;

	    taskQueue = new LinkedList();
	    for (int i = 0; i < numThreads; i++) {
	      new PooledThread().start();
	    }
	  }

	  /**
	   * Requests a new task to run. This method returns immediately, and the task
	   * executes on the next available idle thread in this ThreadPool.
	   * <p>
	   * Tasks start execution in the order they are received.
	   * 
	   * @param task
	   *            The task to run. If null, no action is taken.
	   * @throws IllegalStateException
	   *             if this ThreadPool is already closed.
	   */
	  public synchronized void runTask(Runnable task) {
	    if (!isAlive) {
	      throw new IllegalStateException();
	    }
	    if (task != null) {
	      taskQueue.add(task);
	      notify();
	    }

	  }

	  protected synchronized Runnable getTask() throws InterruptedException {
	    while (taskQueue.size() == 0) {
	      if (!isAlive) {
	        return null;
	      }
	      wait();
	    }
	    return (Runnable) taskQueue.removeFirst();
	  }

	  /**
	   * Closes this ThreadPool and returns immediately. All threads are stopped,
	   * and any waiting tasks are not executed. Once a ThreadPool is closed, no
	   * more tasks can be run on this ThreadPool.
	   */
	  public synchronized void close() {
	    if (isAlive) {
	      isAlive = false;
	      taskQueue.clear();
	      interrupt();
	    }
	  }

	  /**
	   * Closes this ThreadPool and waits for all running threads to finish. Any
	   * waiting tasks are executed.
	   */
	  public void join() {
	    // notify all waiting threads that this ThreadPool is no
	    // longer alive
	    synchronized (this) {
	      isAlive = false;
	      notifyAll();
	    }

	    // wait for all threads to finish
	    Thread[] threads = new Thread[activeCount()];
	    int count = enumerate(threads);
	    for (int i = 0; i < count; i++) {
	      try {
	        threads[i].join();
	      } catch (InterruptedException ex) {
	      }
	    }
	  }

	  /**
	   * A PooledThread is a Thread in a ThreadPool group, designed to run tasks
	   * (Runnables).
	   */
	  private class PooledThread extends Thread {

	    public PooledThread() {
	      super(ThreadPool.this, "PooledThread-" + (threadID++));
	    }

	    public void run() {
	      while (!isInterrupted()) {

	        // get a task to run
	        Runnable task = null;
	        try {
	          task = getTask();
	        } catch (InterruptedException ex) {
	        }

	        // if getTask() returned null or was interrupted,
	        // close this thread by returning.
	        if (task == null) {
	          return;
	        }

	        // run the task, and eat any exceptions it throws
	        try {
	          task.run();
	        } catch (Throwable t) {
	          uncaughtException(this, t);
	        }
	      }
	    }
	  }
}
